﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Iot.Shared.Helper;

namespace Iot.Shared.Path;

public static class DevicePathExtension // 定义类为DevicePathExtension
{
    /// <summary>
    ///     根路径名称
    /// </summary>
    private const string Root = "root";

    /// <summary>
    ///     反引号
    /// </summary>
    private const char Backtick‌ = '`';

    /// <summary>
    ///     根路径地址
    /// </summary>
    public const string RootPath = Root + DevicePath.SeparatorStr;

    private static readonly ConcurrentDictionary<(string Name, DevicePath? Super), DevicePath>
        DevicePathDic = []; // 定义静态的并发字典，键为PathKey，值为DevicePath

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <param name="path"></param>
    /// <param name="name">
    ///     节点名只支持中英文字符、数字、下划线、英文句号和反引号的组合，如果想设置为纯数字或者包含下划线和英文句号，需要用反引号(``)把 节点名称引起来。
    ///     其中``内，两个反引号表示一个反引号，例如 ```` 表示`。
    /// </param>
    /// <returns></returns>
    public static DevicePath Creation(this DevicePath? path, string name)
    {
        var item = name.Formatting();
        lock (DevicePathDic)
        {
            return DevicePathDic.GetOrAdd(ValueTuple.Create(item, path),
                static key => new DevicePath(key.Name, key.Super)); // 从字典中获取键为PathKey的值，如果不存在，则添加一个新的键值对
        }
    }

    /// <summary>
    ///     判断路径是否以原始跟路径开通
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public static bool IsOriginalRootPath(this string path)
    {
        return path.StartsWith(RootPath, StringComparison.Ordinal);
    }

    private static string Formatting(this string name)
    {
        if (name == Root || (name.StartsWith(Backtick‌) && name.EndsWith(Backtick‌))) return name;
        var str = new StringBuilder();
        if (!name.StartsWith(Backtick‌))
            str.Append(Backtick‌);
        str.Append(name);
        if (!name.EndsWith(Backtick‌))
            str.Append(Backtick‌);
        return str.ToString();
    }

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <param name="path"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public static DevicePath Creation(this DevicePath? path, long id)
    {
        return path.Creation($"{id:X2}"); // 调用Creation方法，传入id和分隔符
    }

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="path"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public static DevicePath Creation<T>(this DevicePath? path, T id) where T : Enum
    {
        return Creation(path, id.GetDisplayName()); // 调用Creation方法，传入id和分隔符
    }

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <param name="name">
    ///     Database 节点名只支持中英文字符、数字、下划线、英文句号和反引号的组合，如果想设置为纯数字或者包含下划线和英文句号，需要用反引号(``)把 database
    ///     名称引起来。其中``内，两个反引号表示一个反引号，例如 ```` 表示`。
    /// </param>
    /// <returns></returns>
    public static DevicePath Creation(string name)
    {
        return Creation(null, name); // 调用Creation方法，传入name和分隔符
    }

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public static DevicePath Creation(long id)
    {
        return Creation(null, id); // 调用Creation方法，传入id和分隔符
    }

    /// <summary>
    ///     定义方法，创建DevicePath
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="id"></param>
    /// <returns></returns>
    public static DevicePath Creation<T>(T id) where T : Enum
    {
        return Creation(null, id.GetDisplayName()); // 调用Creation方法，传入id和分隔符
    }

    /// <summary>
    ///     定义方法，解析DevicePath
    /// </summary>
    /// <param name="path"></param>
    /// <param name="super"></param>
    /// <returns></returns>
    public static DevicePath Resolver(this string path, DevicePath? super = null)
    {
        var paths = SplitString(path);
        return paths.Aggregate(super, static (result, item) => result.Creation(item))!;
    }


    private static List<string> SplitString(string input)
    {
        var result = new List<string>();
        var currentSegment = new StringBuilder();
        var inBacktick = false;

        foreach (var c in input)
        {
            switch (c)
            {
                case Backtick‌:
                    // 切换反引号状态
                    inBacktick = !inBacktick;
                    // 添加反引号到当前段
                    currentSegment.Append(c);
                    break;
                case DevicePath.Separator when !inBacktick:
                    // 不在反引号内遇到点号，完成当前段
                    result.Add(currentSegment.ToString());
                    currentSegment.Clear();
                    break;
                default:
                    // 普通字符，添加到当前段
                    currentSegment.Append(c);
                    break;
            }
        }

        // 添加最后一个段
        if (currentSegment.Length > 0)
        {
            result.Add(currentSegment.ToString());
        }

        return result;
    }
}